home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC World 2007 June
/
PCWorld_2007-06_cd.bin
/
v cisle
/
tclock
/
tclocklight-040702-3.exe
/
source
/
dll
/
startmenu.c
< prev
next >
Wrap
C/C++ Source or Header
|
2004-05-19
|
18KB
|
698 lines
/*-------------------------------------------------------------
startmenu.c : customize start menu
(C) 1997-2003 Kazuto Sato
Please read readme.txt about the license.
Written by Kazubon, Nanashi-san
---------------------------------------------------------------*/
#include "tcdll.h"
#include "newapi.h"
/* Globals */
void InitStartMenu(HWND hwndClock);
void EndStartMenu(void);
void ResetStartMenu(HWND hwndClock);
void ClearStartMenuResource(void);
void CheckStartMenu(void);
BOOL OnDrawItemStartMenu(HWND hwnd, DRAWITEMSTRUCT* pdis);
/* Statics */
static void InitStartMenuSetting(HWND hwndClock);
static BOOL IsStartMenu(HMENU hmenu);
static void SubclassBaseBar(void);
static void UnSubclassBaseBar(void);
static void SubclassUserPaneXP(void);
static void UnSubclassUserPaneXP(void);
static void TransStartMenu(void);
static void UnTransStartMenu(void);
static LRESULT CALLBACK WndProcBaseBar(HWND hwnd, UINT message,
WPARAM wParam, LPARAM lParam);
static void OnPaintStartmenuIE4(HWND hwnd, HDC hdc, BOOL bPrint);
static LRESULT CALLBACK WndProcUserPaneXP(HWND hwnd, UINT message,
WPARAM wParam, LPARAM lParam);
static void OnPaintUserPaneXP(HWND hwnd, HDC hdc);
// Start menu (BaseBar) of IE 4 or later
static HWND m_hwndBaseBar = NULL; // window handle
static WNDPROC m_oldWndProcBaseBar = NULL; // window procedure
// Start menu (DV2ControlHost) of Windows XP
static HWND m_hwndDV2ContHost = NULL; // window handle
static HWND m_hwndUserPaneXP = NULL; // window handle of top pane
static WNDPROC m_oldWndProcUserPaneXP = NULL; // window procedure of top pane
static BOOL m_bStartMenu = FALSE; // customize start menu
static BOOL m_bSubclass = FALSE; // subclassify
static HDC m_hdcMemMenu = NULL; // offscreen DC
static HBITMAP m_hbmpMenu = NULL; // offscreen BMP
static COLORREF m_colMenu; // color
static BOOL m_bTile = FALSE; // tile
static int m_alpha = 255; // transparency
static char *m_section = "StartMenu";
/*--------------------------------------------------
initialize
----------------------------------------------------*/
void InitStartMenu(HWND hwndClock)
{
InitStartMenuSetting(hwndClock);
// XP
if(g_winver&WINXP) SubclassUserPaneXP();
// IE 4 or later
if(g_bIE4) SubclassBaseBar();
if((g_winver&WIN2000) && m_hwndBaseBar)
TransStartMenu();
}
/*--------------------------------------------------
clear up
----------------------------------------------------*/
void EndStartMenu(void)
{
if(g_bIE4) UnSubclassBaseBar();
if(g_winver&WINXP) UnSubclassUserPaneXP();
if((g_winver&WIN2000) && m_alpha < 255) UnTransStartMenu();
ClearStartMenuResource();
}
/*--------------------------------------------------
refresh settings
----------------------------------------------------*/
void ResetStartMenu(HWND hwndClock)
{
BOOL bOld = m_bSubclass;
int oldalpha = m_alpha;
ClearStartMenuResource();
InitStartMenuSetting(hwndClock);
if(!bOld && m_bSubclass)
{
if(g_bIE4) SubclassBaseBar();
if(g_winver&WINXP) SubclassUserPaneXP();
}
else if(bOld && !m_bSubclass)
{
if(g_winver&WINXP) UnSubclassUserPaneXP();
if(g_bIE4) UnSubclassBaseBar();
}
if(g_winver&WIN2000)
{
if(m_alpha < 255)
{
if(m_hwndBaseBar)
TransStartMenu();
else if(m_hwndDV2ContHost)
{
if((GetWindowLong(m_hwndDV2ContHost, GWL_EXSTYLE)
& WS_EX_LAYERED))
TransStartMenu();
}
}
else if(oldalpha < 255 && m_alpha == 255)
UnTransStartMenu();
}
}
/*--------------------------------------------------
clear up resources
----------------------------------------------------*/
void ClearStartMenuResource(void)
{
if(m_hdcMemMenu) DeleteDC(m_hdcMemMenu);
m_hdcMemMenu = NULL;
if(m_hbmpMenu) DeleteObject(m_hbmpMenu);
m_hbmpMenu = NULL;
}
/*--------------------------------------------------
check if start menu is destroyed
called in OnTimerMain of wndproc.c
----------------------------------------------------*/
void CheckStartMenu(void)
{
if(m_hwndBaseBar && !IsWindow(m_hwndBaseBar))
{
SubclassBaseBar();
if((g_winver&WIN2000) && m_hwndBaseBar)
TransStartMenu();
}
if(m_hwndDV2ContHost && !IsWindow(m_hwndDV2ContHost))
{
SubclassUserPaneXP();
}
}
/*------------------------------------------------
owner-drawn start menu (Win95 without IE 4)
called in taskbar.c
--------------------------------------------------*/
BOOL OnDrawItemStartMenu(HWND hwnd, DRAWITEMSTRUCT* pdis)
{
HDC hdc, hdcMem;
HBITMAP hbmpMem;
RECT rcBox, rcItem;
HBRUSH hbr;
if(!m_bStartMenu) return FALSE;
if(!IsStartMenu((HMENU)pdis->hwndItem)) return FALSE;
hdc = pdis->hDC;
CopyRect(&rcItem, &(pdis->rcItem));
GetClipBox(hdc, &rcBox); // menu size
// offscreen DC and BMP
hdcMem = CreateCompatibleDC(hdc);
hbmpMem = CreateCompatibleBitmap(hdc, rcBox.right, rcBox.bottom);
SelectObject(hdcMem, hbmpMem);
hbr = CreateSolidBrush(GetSysColor(COLOR_MENU));
FillRect(hdcMem, &rcBox, hbr);
SelectObject(hdcMem, (HFONT)GetCurrentObject(hdc, OBJ_FONT));
// background and text color
if(pdis->itemState & ODS_FOCUS)
{
SetTextColor(hdcMem, GetSysColor(COLOR_HIGHLIGHTTEXT));
SetBkColor(hdcMem, GetSysColor(COLOR_HIGHLIGHT));
}
else
{
SetTextColor(hdcMem, GetSysColor(COLOR_MENUTEXT));
SetBkColor(hdcMem, GetSysColor(COLOR_MENU));
}
// default drawing
pdis->hDC = hdcMem;
CallOldTaskbarWndProc(hwnd, WM_DRAWITEM, 0, (LPARAM)pdis);
// width of "Windows95"
rcItem.right = pdis->rcItem.left;
if(rcItem.right > 0)
{
COLORREF col;
if(!m_bTile)
{
col = m_colMenu;
if(col & 0x80000000) col = GetSysColor(col & 0x00ffffff);
hbr = CreateSolidBrush(col);
FillRect(hdcMem, &rcItem, hbr);
DeleteObject(hbr);
}
if(m_hdcMemMenu && m_hbmpMenu)
{
int i, j;
int wbmp, hbmp;
GetBmpSize(m_hbmpMenu, &wbmp, &hbmp);
for(i = 0; ; i++)
{
int y, ysrc, h, x, w;
for(j = 0; ; j++)
{
y = rcBox.bottom - ((i + 1) * hbmp);
ysrc = 0;
h = hbmp;
if(y < 0)
{
y = 0;
ysrc = ((i + 1) * hbmp) - rcBox.bottom;
h -= ysrc;
}
x = j * wbmp; w = wbmp;
if(x + w > rcItem.right)
{
w -= ((j + 1) * wbmp) - rcItem.right;
}
if(w > 0 && h > 0)
BitBlt(hdcMem, x, y, w, h,
m_hdcMemMenu, 0, ysrc, SRCCOPY);
if(!m_bTile || w < wbmp) break;
}
if(!m_bTile || y == 0) break;
}
}
}
BitBlt(hdc, 0, rcItem.top,
pdis->rcItem.right, rcItem.bottom - rcItem.top,
hdcMem, 0, rcItem.top, SRCCOPY);
pdis->hDC = hdc;
DeleteDC(hdcMem);
DeleteObject(hbmpMem);
return TRUE;
}
/*--------------------------------------------------
read settings
----------------------------------------------------*/
void InitStartMenuSetting(HWND hwndClock)
{
char fname[MAX_PATH], s[MAX_PATH];
m_bStartMenu = GetMyRegLong(NULL, "StartMenu", FALSE);
m_bStartMenu = GetMyRegLong(m_section, "StartMenu", m_bStartMenu);
if(g_winver&WIN2000)
{
m_alpha = GetMyRegLong(NULL, "AlphaStartMenu", 0);
m_alpha = GetMyRegLong(m_section, "Alpha", m_alpha);
m_alpha = 255 - (m_alpha * 255 / 100);
if(m_alpha < 8) m_alpha = 8;
else if(m_alpha > 255) m_alpha = 255;
}
if(m_bStartMenu || m_alpha < 255) m_bSubclass = TRUE;
if(!m_bStartMenu) return;
m_colMenu = GetMyRegLong(NULL, "StartMenuCol",
RGB(128, 128, 128));
m_colMenu = GetMyRegLong(m_section, "Color", m_colMenu);
m_bTile = GetMyRegLong(NULL, "StartMenuTile", FALSE);
m_bTile = GetMyRegLong(m_section, "Tile", m_bTile);
GetMyRegStr(NULL, "StartMenuBmp", s, MAX_PATH, "");
GetMyRegStr(m_section, "Bitmap", fname, MAX_PATH, s);
if(fname[0]) // load bitmap
{
char fname2[MAX_PATH];
RelToAbs(fname2, fname);
m_hbmpMenu = ReadBitmap(hwndClock, fname2, FALSE);
if(m_hbmpMenu)
{
HDC hdc;
hdc = GetDC(hwndClock);
m_hdcMemMenu = CreateCompatibleDC(hdc);
SelectObject(m_hdcMemMenu, m_hbmpMenu);
ReleaseDC(hwndClock, hdc);
}
}
}
/*--------------------------------------------------
HMENU is start menu ?
----------------------------------------------------*/
BOOL IsStartMenu(HMENU hmenu)
{
int i, count, id;
count = GetMenuItemCount(hmenu);
for(i = 0; i < count; i++)
{
id = GetMenuItemID(hmenu, i);
// "Help" item
if(id == 503) return TRUE;
}
return FALSE;
}
/*--------------------------------------------------
subclassify "BaseBar" (Start Menu of IE 4 or later)
----------------------------------------------------*/
void SubclassBaseBar(void)
{
HWND hwnd, hwndChild;
HWND hwndFound;
char classname[80];
m_hwndBaseBar = NULL;
if(m_hwndDV2ContHost) return;
if(!m_bSubclass) return;
// search
hwnd = GetDesktopWindow();
hwnd = GetWindow(hwnd, GW_CHILD);
hwndFound = NULL;
while(hwnd)
{
GetClassName(hwnd, classname, 80);
if(strcmp(classname, "BaseBar") == 0)
{
if(GetWindowThreadProcessId(hwnd, NULL) ==
GetCurrentThreadId())
{
POINT ptParent = { 0, 0 };
RECT rcWinChild;
hwndChild = GetWindow(hwnd, GW_CHILD);
ClientToScreen(hwnd, &ptParent);
GetWindowRect(hwndChild, &rcWinChild);
if(rcWinChild.left - ptParent.x == 21)
{
hwndFound = hwnd; break;
}
else if(rcWinChild.right - rcWinChild.left == 0)
{
if(hwndFound == NULL || (int)hwndFound > (int)hwnd)
hwndFound = hwnd;
}
}
}
hwnd = GetWindow(hwnd, GW_HWNDNEXT);
}
m_hwndBaseBar = hwndFound;
/*{
char s[80];
wsprintf(s, "%X", m_hwndBaseBar);
WriteDebug(s);
}*/
if(m_hwndBaseBar == NULL) return;
// if(IsSubclassed(m_hwndBaseBar)) return;
m_oldWndProcBaseBar = (WNDPROC)GetWindowLong(m_hwndBaseBar, GWL_WNDPROC);
SetWindowLong(m_hwndBaseBar, GWL_WNDPROC, (LONG)WndProcBaseBar);
}
/*--------------------------------------------------
restore window procedure of "BaseBar"
----------------------------------------------------*/
void UnSubclassBaseBar(void)
{
if(m_hwndBaseBar && IsWindow(m_hwndBaseBar))
{
if(m_oldWndProcBaseBar)
SetWindowLong(m_hwndBaseBar, GWL_WNDPROC,
(LONG)m_oldWndProcBaseBar);
}
m_oldWndProcBaseBar = NULL;
}
/*--------------------------------------------------
Subclassify "Desktop User Pane" window of XP Start Menu
----------------------------------------------------*/
void SubclassUserPaneXP(void)
{
if(!m_bSubclass) return;
m_hwndDV2ContHost = FindWindow("DV2ControlHost", NULL);
if(!m_hwndDV2ContHost) return;
m_hwndUserPaneXP = FindWindowEx(m_hwndDV2ContHost, NULL,
"Desktop User Pane", NULL);
if(!m_hwndUserPaneXP) return;
if(IsSubclassed(m_hwndUserPaneXP)) return;
m_oldWndProcUserPaneXP = (WNDPROC)GetWindowLong(m_hwndUserPaneXP,
GWL_WNDPROC);
SetWindowLong(m_hwndUserPaneXP, GWL_WNDPROC, (LONG)WndProcUserPaneXP);
}
/*--------------------------------------------------
restore window procedure of "Desktop User Pane"
----------------------------------------------------*/
void UnSubclassUserPaneXP(void)
{
if(m_hwndUserPaneXP && IsWindow(m_hwndUserPaneXP))
{
if(m_oldWndProcUserPaneXP)
{
SetWindowLong(m_hwndUserPaneXP, GWL_WNDPROC,
(LONG)m_oldWndProcUserPaneXP);
SendMessage(GetParent(m_hwndUserPaneXP), WM_SYSCOLORCHANGE, 0, 0);
}
}
m_oldWndProcUserPaneXP = NULL;
}
/*--------------------------------------------------
set transparency of Start menu
----------------------------------------------------*/
void TransStartMenu(void)
{
LONG style;
if(m_alpha >= 255) return;
if(m_hwndDV2ContHost)
{
if(m_hwndUserPaneXP)
InvalidateRect(m_hwndUserPaneXP, NULL, TRUE);
style = GetWindowLong(m_hwndDV2ContHost, GWL_EXSTYLE);
SetWindowLong(m_hwndDV2ContHost, GWL_EXSTYLE, style|WS_EX_LAYERED);
MySetLayeredWindowAttributes(m_hwndDV2ContHost,
0, (BYTE)m_alpha, LWA_ALPHA);
//InvalidateRect(m_hwndDV2ContHost, NULL, TRUE);
}
if(m_hwndBaseBar)
{
style = GetWindowLong(m_hwndBaseBar, GWL_EXSTYLE);
SetWindowLong(m_hwndBaseBar, GWL_EXSTYLE, style|WS_EX_LAYERED);
MySetLayeredWindowAttributes(m_hwndBaseBar,
0, (BYTE)m_alpha, LWA_ALPHA);
}
}
/*--------------------------------------------------
restore transparency of Start menu
----------------------------------------------------*/
void UnTransStartMenu(void)
{
LONG style;
if(m_hwndDV2ContHost)
{
style = GetWindowLong(m_hwndDV2ContHost, GWL_EXSTYLE);
style &= ~WS_EX_LAYERED;
SetWindowLong(m_hwndDV2ContHost, GWL_EXSTYLE, style);
MySetLayeredWindowAttributes(m_hwndDV2ContHost,
GetSysColor(COLOR_3DFACE), 0, LWA_COLORKEY);
InvalidateRect(m_hwndDV2ContHost, NULL, TRUE);
}
if(m_hwndBaseBar)
{
style = GetWindowLong(m_hwndBaseBar, GWL_EXSTYLE);
style &= ~WS_EX_LAYERED;
SetWindowLong(m_hwndBaseBar, GWL_EXSTYLE, style);
MySetLayeredWindowAttributes(m_hwndBaseBar,
GetSysColor(COLOR_3DFACE), 0, LWA_COLORKEY);
}
}
/*------------------------------------------------
window procedure of Start Menu (BaseBar)
of IE 4 or later
--------------------------------------------------*/
LRESULT CALLBACK WndProcBaseBar(HWND hwnd, UINT message,
WPARAM wParam, LPARAM lParam)
{
switch(message)
{
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc;
if(!m_bStartMenu) break;
hdc = BeginPaint(hwnd, &ps);
OnPaintStartmenuIE4(hwnd, hdc, FALSE);
EndPaint(hwnd, &ps);
return 0;
}
case WM_PRINT:
{
LRESULT r;
if(!m_bStartMenu) break;
r = CallWindowProc(m_oldWndProcBaseBar,
hwnd, message, wParam, lParam);
OnPaintStartmenuIE4(hwnd, (HDC)wParam, TRUE);
return r;
}
case WM_STYLECHANGED:
{
STYLESTRUCT* pss = (STYLESTRUCT*)lParam;
if(m_alpha < 255 && wParam == GWL_EXSTYLE &&
!(pss->styleNew & WS_EX_LAYERED))
{
TransStartMenu();
return 0;
}
break;
}
}
return CallWindowProc(m_oldWndProcBaseBar, hwnd, message, wParam, lParam);
}
/*------------------------------------------------
paint StartMenu (BaseBar) of IE 4 or later
--------------------------------------------------*/
void OnPaintStartmenuIE4(HWND hwnd, HDC hdc, BOOL bPrint)
{
RECT rc, rcWin, rcChild;
POINT pt;
COLORREF col;
HBRUSH hbr;
BITMAP bmp;
int hClient, wClient;
GetWindowRect(GetWindow(hwnd, GW_CHILD), &rcChild);
GetWindowRect(hwnd, &rcWin);
GetClientRect(hwnd, &rc);
pt.x = 0; pt.y = 0;
ClientToScreen(hwnd, &pt);
if(pt.x == rcChild.left) return;
rc.right = 21;
wClient = rc.right; hClient = rc.bottom;
if(bPrint)
{
int dx, dy;
dx = pt.x - rcWin.left; dy = pt.y - rcWin.top;
rc.left += dx; rc.right += dx;
rc.top += dy; rc.bottom += dy;
}
// fill with color
col = m_colMenu;
if(col & 0x80000000) col = GetSysColor(col & 0x00ffffff);
hbr = CreateSolidBrush(col);
FillRect(hdc, &rc, hbr);
DeleteObject(hbr);
// draw bitmap
if(m_hbmpMenu)
{
int i, j;
GetObject(m_hbmpMenu, sizeof(BITMAP), &bmp);
for(i = 0; ; i++)
{
int y, ysrc, h, x, w;
for(j = 0; ; j++)
{
y = hClient - ((i + 1) * bmp.bmHeight);
ysrc = 0;
h = bmp.bmHeight;
if(y < 0)
{
y = 0;
ysrc = ((i + 1) * bmp.bmHeight) - hClient;
h -= ysrc;
}
x = j * bmp.bmWidth; w = bmp.bmWidth;
if(x + w > wClient)
{
w -= ((j + 1) * bmp.bmWidth) - wClient;
}
if(w > 0 && h > 0)
BitBlt(hdc, rc.left + x, rc.top + y, w, h,
m_hdcMemMenu, 0, ysrc, SRCCOPY);
if(!m_bTile || w < bmp.bmWidth) break;
}
if(!m_bTile || y == 0) break;
}
}
}
/*------------------------------------------------
window procedure of
top child window of XP Start Menu
--------------------------------------------------*/
LRESULT CALLBACK WndProcUserPaneXP(HWND hwnd, UINT message,
WPARAM wParam, LPARAM lParam)
{
switch(message)
{
case WM_NOTIFY:
if(m_alpha < 255)
{
LONG style = GetWindowLong(hwnd, GWL_EXSTYLE);
if(!(style&WS_EX_LAYERED))
PostMessage(hwnd, WM_USER+1, 0, 0);
}
if(m_bStartMenu)
{
HDC hdc = GetDC(hwnd);
OnPaintUserPaneXP(hwnd, hdc);
ReleaseDC(hwnd, hdc);
return 0;
}
break;
case (WM_USER+1):
if(m_alpha < 255)
TransStartMenu();
return 0;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc;
if(!m_bStartMenu) break;
hdc = BeginPaint(hwnd, &ps);
OnPaintUserPaneXP(hwnd, hdc);
EndPaint(hwnd, &ps);
return 0;
}
case WM_CTLCOLORSTATIC:
if(m_bStartMenu) return 0;
break;
case WM_DRAWITEM:
if(m_bStartMenu) return 0;
break;
}
return CallWindowProc(m_oldWndProcUserPaneXP,
hwnd, message, wParam, lParam);
}
/*----------------------------------------------------
paint "Desktop User Pane" window of XP Start Menu
-----------------------------------------------------*/
void OnPaintUserPaneXP(HWND hwnd, HDC hdc)
{
RECT rc;
COLORREF col;
HBRUSH hbr;
int wClient, hClient;
GetClientRect(hwnd, &rc);
wClient = rc.right; hClient = rc.bottom;
col = m_colMenu;
if(col & 0x80000000) col = GetSysColor(col & 0x00ffffff);
hbr = CreateSolidBrush(col);
FillRect(hdc, &rc, hbr);
DeleteObject(hbr);
if(m_hbmpMenu)
{
int x, y;
int wbmp, hbmp;
GetBmpSize(m_hbmpMenu, &wbmp, &hbmp);
for(y = 0; y < hClient; y += hbmp)
{
for(x = 0; x < wClient; x += wbmp)
{
BitBlt(hdc, x, y, wbmp, hbmp, m_hdcMemMenu, 0, 0, SRCCOPY);
if(!m_bTile) break;
}
if(!m_bTile) break;
}
}
}